




#include <cmath>

#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "pie3dchartpoints.h"
#endif

#include <wx/wxprec.h>

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif

#include "wx/label.h"
#include "wx/pie3dchartpoints.h"
#include "wx/chartsizes.h"



const int SHADOW_DEEP = 20;
const double ELLISSE_W = 2;
const double ELLISSE_H = 0.75;



//----------------------------------------------------------------------E-+++
static inline double DegToRad(
	double deg
) {
	return (deg * M_PI) / 180.0;
}



//----------------------------------------------------------------------E-+++
static inline wxPoint EllipsePoint(
    int w,
    int h,
    int x0,
    int y0,
    double rad
) {
    int halfW = static_cast<int>( floor((double)w/2) );
    int halfH = static_cast<int>( floor((double)h/2) );

    int x = x0 + halfW + static_cast<int>( floor(halfW * cos(rad)) );
    int y = y0 + halfH - static_cast<int>( floor(halfH * sin(rad)) );

    return wxPoint( x, y );
}




wxPie3DChartPoints::wxPie3DChartPoints(
	wxString name,
	ChartColor c,
    bool showlabel
) : wxChartPoints(wxChartPointsTypes::Pie3D()),
	m_Name(name),
	m_Color(c),
	m_Zoom(1),
	m_PieTag(NONE),
    m_ShowLabel(showlabel) {
}


//----------------------------------------------------------------------E-+++
ChartValue wxPie3DChartPoints::GetXVal(
	int n
) const {
	return ( m_Points.GetXVal(n) );
}


//----------------------------------------------------------------------E-+++
ChartValue wxPie3DChartPoints::GetYVal(
	int n
) const {
	return ( m_Points.GetYVal(n) );
}


//----------------------------------------------------------------------E-+++
wxString wxPie3DChartPoints::GetName(
	int n
) const {
	return ( m_Points.GetName(n) );
}


//----------------------------------------------------------------------E-+++
ChartColor wxPie3DChartPoints::GetColor(int n) const {
	return ( m_Points.GetColor(n) );
}


//----------------------------------------------------------------------E-+++
int wxPie3DChartPoints::GetCount() const {
	return ( m_Points.GetCount() );
}


//----------------------------------------------------------------------E-+++
ChartValue wxPie3DChartPoints::GetMaxX() const {

	return ( 0 );
}


//----------------------------------------------------------------------E-+++
ChartValue wxPie3DChartPoints::GetMaxY() const {
//	return ( m_Points.GetMaxY() );
	return ( 0 );
}


//----------------------------------------------------------------------E-+++
ChartValue wxPie3DChartPoints::GetMinX() const {
//	return ( m_Points.GetMinX() );
	return ( 0 );
}


//----------------------------------------------------------------------E-+++
ChartValue wxPie3DChartPoints::GetMinY() const {
//	return ( m_Points.GetMinY() );
	return ( 0 );
}


void wxPie3DChartPoints::SetZoom(
	double z
) {
	m_Zoom = z;
}


//----------------------------------------------------------------------E-+++
double wxPie3DChartPoints::GetZoom() {
    return ( (m_Zoom = m_Sizes->GetXZoom()) );
}


void wxPie3DChartPoints::SetSizes(
	wxChartSizes *sizes
) {
	m_Sizes = sizes;
}


//----------------------------------------------------------------------E-+++
wxChartSizes* wxPie3DChartPoints::GetSizes() const {
    return ( m_Sizes );
}


//----------------------------------------------------------------------E-+++
ChartColor wxPie3DChartPoints::GetColor() const {
	return ( m_Color );
}


void wxPie3DChartPoints::SetColor(
	ChartColor c
) {
	m_Color = c;
}


//----------------------------------------------------------------------E-+++
wxString wxPie3DChartPoints::GetName() const {
	return ( m_Name );
}


void wxPie3DChartPoints::SetName(
	wxString name
) {
	m_Name =  name;
}



void wxPie3DChartPoints::Add(
	wxString name,
	ChartValue x,
	ChartValue y
) {
	Add( name, x, y, wxCHART_NOCOLOR );
}



void wxPie3DChartPoints::Add(
	wxString name,
	ChartValue x,
	ChartValue y,
	ChartColor c
) {
	if ( c == wxCHART_NOCOLOR )
		c = wxChartColors::GetColor();
	m_Points.Add( name, x, y, c );
}


void wxPie3DChartPoints::SetDisplayTag(
 	wxDISPLAY_LABEL d
) {
	m_PieTag = d;
}


//----------------------------------------------------------------------E-+++
wxDISPLAY_LABEL wxPie3DChartPoints::GetDisplayTag() const {
	return ( m_PieTag );
}



void wxPie3DChartPoints::Draw(
    CHART_HPAINT hp,
    CHART_HRECT hr
) {

   
   
   
    wxChartSizes *sizes = GetSizes();

   
   
   
    int r = (int)wxMin( (int)hr->w / 2,
        (int)(hr->h - 2 * sizes->GetSizeHeight() * ELLISSE_H) / 2 );

    if ( r > 0 )
    {
        int iNodes = GetCount();

        if ( iNodes > 0 )
        {
            int iData;
            int ValTot;
            int iDatas = GetCount();
            for ( iData = 0, ValTot = 0; iData < iDatas; ++ iData )
                ValTot += static_cast<int>(GetYVal( iData ));

            hp->SetPen( *wxBLACK_PEN );

            double percent;
            double grad, grad1;
            double rad;
            int deep;
            int x, y, w, h;

		
            w = (int)floor(r * ELLISSE_W);
			h = (int)floor(r * ELLISSE_H);

		
            x = hr->x + hr->w/2 - w/2;
            y = hr->y + hr->h/2 - h;

           
            deep = (int)floor( SHADOW_DEEP * GetZoom() );

		
		
		

			hp->DrawEllipticArc(
				x,
				y + deep,
				w,
				h,
				175,
				360);
			hp->DrawEllipticArc(
				x,
				y + deep,
				w,
				h,
				0,
				5);

		
			rad = DegToRad( 180 );

			hp->DrawLine(
                EllipsePoint( w, h, x, y, rad ).x,
                EllipsePoint( w, h, x, y, rad ).y,
                EllipsePoint( w, h, x, y, rad ).x,
                EllipsePoint( w, h, x, y + deep, rad ).y + 1
            );

		
			rad = DegToRad( 360 );

            hp->DrawLine(
                EllipsePoint( w, h, x, y, rad ).x,
                EllipsePoint( w, h, x, y, rad ).y,
                EllipsePoint( w, h, x, y, rad ).x,
                EllipsePoint( w - 180, h, x, y + deep, rad ).y
            );

			grad = 0;
		
            for ( iData = 0; iData < iDatas; ++ iData )
            {
                hp->SetPen( *wxBLACK_PEN );
                hp->SetBrush( wxBrush(GetColor(iData), wxSOLID) );

               
                percent = (double)(GetYVal(iData) * 100) / (double)ValTot;
                grad1    = grad + (double)(percent * 360) / (double)100;
                rad     = DegToRad( grad );

                hp->DrawEllipticArc( x, y, w, h, grad, grad1);

               
               
               
                if ( grad1 > 180 )
                {
				
				

                   
                    hp->SetPen(
                        wxPen(wxChartColors::GetDarkColor(
                            GetColor(iData), 15))
                    );
                    hp->SetBrush(
                        wxBrush(wxChartColors::GetDarkColor(
                            GetColor(iData), 15),
                        wxSOLID)
                    );

                   
                    if ( grad1 < 360 )
                    {
                        hp->DrawLine(
                            EllipsePoint( w, h, x, y, DegToRad( grad1 ) ).x,
                            EllipsePoint( w, h, x, y, DegToRad( grad1 ) ).y - 1,
                            EllipsePoint( w, h, x, y, DegToRad( grad1 ) ).x,
                            EllipsePoint( w, h, x, y + deep,
                                DegToRad( grad1 ) ).y + 1
                        );
                    }
                    hp->FloodFill(
                        EllipsePoint( w, h, x, y,
                            DegToRad( grad1 ) ).x - 3,
                        (int)floor(EllipsePoint( w, h, x, y,
                            DegToRad( grad1 ) ).y + (double)deep/2),
                        *wxWHITE
                    );
				}

               
               
               
                if (!m_ShowLabel)
                    continue;

                wxString lbl;
                wxLabel wxLbl;

                LABEL_POSITION p;
                if ( grad < 90 ||
                    grad > 270 )
                    p = RIGHT;
                else
                    p = LEFT;
                if ( grad  > 180 )
                    p = (LABEL_POSITION)( p | DOWN );
                else
                    p = (LABEL_POSITION)( p | UP );

                switch ( GetDisplayTag() )
                {
                case XVALUE:
                    lbl.Printf( wxT("%d"), static_cast<int>(GetXVal(iData)) );
                    wxLbl.Draw( hp,
                        EllipsePoint( w, h, x, y, DegToRad( grad ) ).x,
                        EllipsePoint( w, h, x, y, DegToRad( grad ) ).y,
                        GetColor(iData), lbl, p );
                    break;
                case YVALUE:
                    lbl.Printf( wxT("%d"), static_cast<int>(GetYVal(iData)) );
                    wxLbl.Draw( hp,
                        EllipsePoint( w, h, x, y, DegToRad( grad ) ).x,
                        EllipsePoint( w, h, x, y, DegToRad( grad ) ).y,
                        GetColor(iData), lbl, p );
                    break;
                case XVALUE_FLOAT:
                    lbl.Printf( wxT("%4.1f"), GetXVal(iData) );
                    wxLbl.Draw( hp,
                                EllipsePoint( w, h, x, y, DegToRad( grad ) ).x,
                                EllipsePoint( w, h, x, y, DegToRad( grad ) ).y,
                                GetColor(iData), lbl, p );
                    break;
                case YVALUE_FLOAT:
                    lbl.Printf( wxT("%4.1f"), GetYVal(iData) );
                    wxLbl.Draw( hp,
                                EllipsePoint( w, h, x, y, DegToRad( grad ) ).x,
                                EllipsePoint( w, h, x, y, DegToRad( grad ) ).y,
                                GetColor(iData), lbl, p );
                    break;
                    case NAME:
                    lbl = GetName(iData).c_str();
                    wxLbl.Draw( hp,
                        EllipsePoint( w, h, x, y, DegToRad( grad ) ).x,
                        EllipsePoint( w, h, x, y, DegToRad( grad ) ).y,
                        GetColor(iData), lbl, p );
                    break;
                case NONE:
                default:
                    break;
                }

                grad = grad1;

            }

        }
    }
}



wxPie3DChartPoints* wxPie3DChartPoints::CreateWxPie3DChartPoints(
    wxString name,
    ChartColor c,
    bool showlabel
) {
    if ( c == wxCHART_NOCOLOR )
        c = wxChartColors::GetColor();

    return new wxPie3DChartPoints( name, c, showlabel );
}
